import datetime
import json
import os
import uuid
from functools import wraps

from django.db.models import Count
from django.shortcuts import redirect, render
from jwt import decode as jwt_decode
from django.forms import model_to_dict
from django.http import JsonResponse
from auth_app.models import User
from django_it_community import settings
from it_app.models import Type, Article, Follow, Collect, Notice, Message, Comment, ReportArticle, ReportComment


# 定义装饰器，在请求前判断是否为超级管理员
def is_login(func):
    @wraps(func)
    def wrapper(request, *args, **kwargs):
        # 获取当前用户id
        user_id = jwt_decode(request.headers.get('Authorization').split(' ')[-1], settings.SECRET_KEY, algorithms=["HS256"])['user_id']
        if user_id:
            return func(request, *args, **kwargs)
        else:
            return JsonResponse({"code": 9, "msg": "No permission"})

    return wrapper


def toAdmin(request):
    return redirect('/admin/')


# 获取当前用户
def get_current_user(request):
    # 获取当前用户id
    user_id = None
    authorization = request.headers.get('Authorization')
    if authorization:
        user_id = jwt_decode(authorization.split(' ')[-1], settings.SECRET_KEY, algorithms=["HS256"])['user_id']
    return user_id


# -------------------------用户端-获取分类---------------------------------------
def get_type(request):
    try:
        rd = json.loads(request.body)
        qs = Type.objects.all()
        res_data = [model_to_dict(i) for i in qs]
        return JsonResponse({"code": 0, "msg": "", "data": res_data})
    except Exception as e:
        print(e)
        return JsonResponse({"code": 9, "msg": str(e), "data": {}})


# -------------------------用户端-获取标签---------------------------------------
def get_tag(request):
    try:
        rd = json.loads(request.body)
        qs = Article.objects.all()
        tem = []
        for i in qs:
            if i.tag:
                tem += i.tag.split(',')
        return JsonResponse({"code": 0, "msg": "", "data": list(set(tem))})
    except Exception as e:
        print(e)
        return JsonResponse({"code": 9, "msg": str(e), "data": {}})


# -------------------------用户端-获取用户的详细信息（关注，收藏，文章数等信息）---------------------------------------
def get_user_detail(request):
    try:
        user_id = get_current_user(request)

        rd = json.loads(request.body)
        print(user_id)
        print(rd.get('user_id'))
        user = User.objects.get(id=rd.get('user_id'))
        art = {
            "first_name": user.first_name,
            "ava": user.ava,
            "col_num": user.collect_set.count(),
            "fol_num": user.being_followed.count(),
            "art_num": user.article_set.count(),
            "is_followed": Follow.objects.filter(being_followed_id=user.id, follower_id=user_id).exists() if user_id else False,
        }
        return JsonResponse({"code": 0, "msg": "", "data": art})
    except Exception as e:
        print(e)
        return JsonResponse({"code": 9, "msg": str(e), "data": {}})


# -------------------------用户端-获取文章列表---------------------------------------
def get_article_list(request):
    try:
        rd = json.loads(request.body)
        qs = Article.objects.filter(examine=1, rang=1, status=1, type_id=rd.get('type'))
        total = qs.count()
        qs = qs[(rd['page_index'] - 1) * rd['page_size']:(rd['page_index']) * rd['page_size']]
        res_data = [{**model_to_dict(i), "user": i.user.first_name, "user_id": i.user.id, "collect": i.collect_set.count()} for i in qs]
        return JsonResponse({"code": 0, "msg": "", "data": {"data": res_data, "total": total}})
    except Exception as e:
        print(e)
        return JsonResponse({"code": 9, "msg": str(e), "data": {}})


# -------------------------用户端-浏览文章-文章详细信息---------------------------------------
def watch_article_by_id(request):
    try:
        rd = json.loads(request.body)
        qs = Article.objects.get(id=rd.get('id'))
        qs.readers += 1
        qs.save()
        # 获取当前用户id
        user_id = get_current_user(request)
        return JsonResponse({"code": 0, "msg": "", "data": {
            **model_to_dict(qs),
            "first_name": qs.user.first_name,
            "user_id": qs.user.id,
            "col_num": qs.collect_set.count(),
            "comment_num": qs.comment_set.filter(status=1).count(),
            "is_collected": qs.collect_set.filter(user_id=user_id).exists() if user_id else False,
            "update_time": qs.update_time.strftime("%Y-%m-%d %H:%M:%S"),
        }})
    except Exception as e:
        print(e)
        return JsonResponse({"code": 9, "msg": str(e), "data": {}})


# -------------------------用户端-浏览文章-文章详细信息---------------------------------------
def get_user_article_list(request):
    try:
        # 获取当前用户id
        user_id = get_current_user(request)
        rd = json.loads(request.body)
        qs = Article.objects.filter(user_id=rd.get('id')).order_by('-update_time')
        total = qs.count()
        qs = qs[(rd['page_index'] - 1) * rd['page_size']:(rd['page_index']) * rd['page_size']]
        res_data = [{
            **model_to_dict(i),
            "create_time": i.create_time.strftime("%Y-%m-%d %H:%M:%S"),
            "first_name": i.user.first_name,
            "col_num": i.collect_set.count(),
        } for i in qs]
        return JsonResponse({"code": 0, "msg": "", "data": {"data": res_data, "total": total}})
    except Exception as e:
        print(e)
        return JsonResponse({"code": 9, "msg": str(e), "data": {}})


# -------------------------用户端-获取文章榜-用户榜---------------------------------------
def get_wzb_data(request):
    try:
        rd = json.loads(request.body)
        qs = Article.objects.filter(examine=1, rang=1, status=1).order_by('-readers')
        res_data = [{**model_to_dict(i), "user_id": i.user_id} for i in qs[:5]]
        return JsonResponse({"code": 0, "msg": "", "data": res_data})
    except Exception as e:
        print(e)
        return JsonResponse({"code": 9, "msg": str(e), "data": {}})


def get_yhb_data(request):
    try:
        # 获取当前用户id
        user_id = get_current_user(request)
        rd = json.loads(request.body)
        qs = User.objects.all()
        res_data = [{
            "username": i.username,
            "ava": i.ava,
            "user_id": i.id,
            "is_followed": Follow.objects.filter(being_followed_id=i.id, follower_id=user_id).exists() if user_id else False
        } for i in qs[:5]]
        return JsonResponse({"code": 0, "msg": "", "data": res_data})
    except Exception as e:
        print(e)
        return JsonResponse({"code": 9, "msg": str(e), "data": {}})


# -------------------------用户端-浏览文章-文章详细信息---------------------------------------
def get_notice(request):
    try:
        qs = Notice.objects.filter(is_show=1).order_by('-update_time')
        res_data = [{**model_to_dict(i)} for i in qs]
        return JsonResponse({"code": 0, "msg": "", "data": res_data})
    except Exception as e:
        print(e)
        return JsonResponse({"code": 9, "msg": str(e), "data": {}})


# -------------------------用户端-关注-收藏---------------------------------------
@is_login
def follow(request):
    try:
        rd = json.loads(request.body)
        # 获取当前用户id
        user_id = jwt_decode(request.headers.get('Authorization').split(' ')[-1], settings.SECRET_KEY, algorithms=["HS256"])['user_id']
        qs = Follow.objects.filter(follower_id=user_id, being_followed_id=rd.get('user_id'))
        if qs.exists():
            qs.delete()
            return JsonResponse({"code": 0, "msg": "已取消关注", "data": {}})
        else:
            Follow.objects.create(
                follower_id=user_id,
                being_followed_id=rd.get('user_id')
            )
            return JsonResponse({"code": 0, "msg": "已关注", "data": {}})
    except Exception as e:
        print(e)
        return JsonResponse({"code": 9, "msg": str(e), "data": {}})


@is_login
def collect(request):
    try:
        rd = json.loads(request.body)
        # 获取当前用户id
        user_id = get_current_user(request)
        qs = Collect.objects.filter(article_id=rd.get('art_id'), user_id=user_id)
        if qs.exists():
            qs.delete()
            return JsonResponse({"code": 0, "msg": "已取消收藏", "data": {}})
        else:
            Collect.objects.create(
                article_id=rd.get('art_id'),
                user_id=user_id
            )
            return JsonResponse({"code": 0, "msg": "已收藏", "data": {}})
    except Exception as e:
        print(e)
        return JsonResponse({"code": 9, "msg": str(e), "data": {}})


# -------------------------用户端-文章管理---------------------------------------
@is_login
def add_article(request):
    if request.method == 'POST':
        try:
            rd = json.loads(request.body)
            # 获取当前用户id
            user_id = jwt_decode(request.headers.get('Authorization').split(' ')[-1], settings.SECRET_KEY, algorithms=["HS256"])['user_id']
            if rd.get('article_id'):
                qs = Article.objects.get(id=rd.get('article_id'))
                qs.title = rd.get('title')
                qs.type_id = rd.get('type')
                qs.content = rd.get('content')
                qs.tag = ','.join(rd.get('tag')) if rd.get('tag') else None
                qs.cover = rd.get('cover')
                qs.summary = rd.get('summary')
                qs.rang = rd.get('rang')
                qs.status = rd.get('status') if rd.get('status') else 2
                qs.examine = rd.get('examine') if rd.get('status') else 0
                qs.user_id = user_id
                qs.save()
                return JsonResponse({"code": 0, "msg": "", "data": {"article_id": qs.id, "update_time": qs.update_time.strftime("%H:%M:%S")}})
            else:
                qs = Article.objects.create(
                    title=rd.get('title'),
                    type=rd.get('type'),
                    content=rd.get('content'),
                    tag=rd.get('tag'),
                    cover=rd.get('cover'),
                    summary=rd.get('summary'),
                    rang=rd.get('rang'),
                    user_id=user_id,
                )
                return JsonResponse({"code": 0, "msg": "提交成功", "data": {"article_id": qs.id, "update_time": qs.update_time.strftime("%H:%M:%S")}})
        except Exception as e:
            print(e)
            return JsonResponse({"code": 9, "msg": str(e), "data": {}})


@is_login
def upload_article_cover(request):
    rd = request.POST
    file = request.FILES.get('file')
    new_file_name = "%s.%s" % (uuid.uuid4(), file.name.split('.')[-1])
    try:
        with open('static/source/%s' % new_file_name, 'wb') as f:
            for chunk in file:
                f.write(chunk)
        qs = Article.objects.get(id=rd.get('id'))
        qs.cover = new_file_name
        qs.save()
        return JsonResponse({"code": 0, "msg": "保存成功", "data": {}})
    except Exception as e:
        print(e)
        return JsonResponse({"code": 9, "msg": "保存失败：" + str(e), "data": {}})


@is_login
def get_my_article(request):
    try:
        # 获取当前用户id
        user_id = get_current_user(request)
        rd = json.loads(request.body)
        qs = Article.objects.filter(status=rd.get('status'), user_id=user_id)
        total = qs.count()
        qs = qs[(rd['page_index'] - 1) * rd['page_size']:(rd['page_index']) * rd['page_size']]
        res_data = [{**model_to_dict(i), "user": i.user.first_name, "collect": i.collect_set.count()} for i in qs]
        return JsonResponse({"code": 0, "msg": "", "data": {"data": res_data, "total": total}})
    except Exception as e:
        print(e)
        return JsonResponse({"code": 9, "msg": str(e), "data": {}})


@is_login
def get_my_message(request):
    # 获取当前用户id
    user_id = get_current_user(request)
    if request.method == 'GET':
        try:
            qs = Message.objects.filter(user_id=user_id).order_by('-update_time')
            res_data = [{**model_to_dict(i), "create_time": i.create_time.strftime("%Y-%m-%d %H:%M:%S")} for i in qs]
            qs.update(is_read=1)
            return JsonResponse({"code": 0, "msg": "", "data": res_data})
        except Exception as e:
            print(e)
            return JsonResponse({"code": 9, "msg": str(e), "data": {}})


@is_login
def get_my_collect(request):
    # 获取当前用户id
    user_id = get_current_user(request)
    if request.method == 'GET':
        try:
            qs = Collect.objects.filter(article__user_id=user_id).order_by('-update_time')
            res_data = [{
                **model_to_dict(i),
                "create_time": i.create_time.strftime("%Y-%m-%d %H:%M:%S"),
                "art_title": i.article.title,
                "username": i.user.username,
                "ava": i.user.ava,
            } for i in qs]
            qs.update(is_read=1)
            return JsonResponse({"code": 0, "msg": "", "data": res_data})
        except Exception as e:
            print(e)
            return JsonResponse({"code": 9, "msg": str(e), "data": {}})


@is_login
def get_my_follow(request):
    # 获取当前用户id
    user_id = get_current_user(request)
    if request.method == 'GET':
        try:
            qs = Follow.objects.filter(being_followed_id=user_id).order_by('-update_time')
            res_data = [{
                **model_to_dict(i),
                "create_time": i.create_time.strftime("%Y-%m-%d %H:%M:%S"),
                "username": i.follower.username,
                "ava": i.follower.ava,
            } for i in qs]
            qs.update(is_read=1)
            return JsonResponse({"code": 0, "msg": "", "data": res_data})
        except Exception as e:
            print(e)
            return JsonResponse({"code": 9, "msg": str(e), "data": {}})

@is_login
def get_my_comment(request):
    # 获取当前用户id
    user_id = get_current_user(request)
    if request.method == 'GET':
        try:
            qs = Comment.objects.filter(article__user_id=user_id).order_by('-update_time')
            res_data = [{
                **model_to_dict(i),
                "create_time": i.create_time.strftime("%Y-%m-%d %H:%M:%S"),
                "art_title": i.article.title,
                "username": i.user.first_name,
                "ava": i.user.ava,
            } for i in qs]
            return JsonResponse({"code": 0, "msg": "", "data": res_data})
        except Exception as e:
            print(e)
            return JsonResponse({"code": 9, "msg": str(e), "data": {}})

@is_login
def delete_article(request):
    try:
        rd = json.loads(request.body)
        qs = Article.objects.get(id=rd.get('id'))
        if qs.cover:
            os.remove('static/source/%s' % qs.cover)
        qs.delete()
        return JsonResponse({"code": 0, "msg": "删除成功", "data": {}})
    except Exception as e:
        print(e)
        return JsonResponse({"code": 9, "msg": "删除失败：" + str(e), "data": {}})


def get_user_article_data(request):
    try:
        rd = json.loads(request.body)
        # 获取当前用户id
        user_id = jwt_decode(request.headers.get('Authorization').split(' ')[-1], settings.SECRET_KEY, algorithms=["HS256"])['user_id']
        today = datetime.date.today()
        yesterday = today - datetime.timedelta(days=1)
        data = {
            "fol": Follow.objects.filter(being_followed=user_id).count(),
            "fol_j": Follow.objects.filter(create_time__date=yesterday).count() - Follow.objects.filter(create_time__date=today).count(),
            "col_j": Collect.objects.filter(create_time__date=yesterday).count() - Collect.objects.filter(create_time__date=today).count(),
            "col": Collect.objects.filter(article__user__id=user_id).count(),
            "art": Article.objects.filter(user_id=user_id).count(),

        }
        return JsonResponse({"code": 0, "msg": "", "data": data})
    except Exception as e:
        print(e)
        return JsonResponse({"code": 9, "msg": str(e), "data": {}})


def search_article(request):
    try:
        rd = json.loads(request.body)
        qs = Article.objects.filter(examine=1, rang=1, status=1, title__contains=rd.get('searchVal')).order_by('-readers')
        total = qs.count()
        qs = qs[(rd['page_index'] - 1) * rd['page_size']:(rd['page_index']) * rd['page_size']]
        res_data = [{
            **model_to_dict(i),
            "first_name": i.user.first_name,
            "user_id": i.user.id,
            "col_num": i.collect_set.count()} for i in qs]
        return JsonResponse({"code": 0, "msg": "", "data": {"data": res_data, "total": total}})
    except Exception as e:
        print(e)
        return JsonResponse({"code": 9, "msg": str(e), "data": {}})


def get_comment_by_article_id(request):
    try:
        rd = json.loads(request.body)
        # 获取顶级评论
        top_qs = Comment.objects.filter(article_id=rd.get('id'), parent_comment_id__isnull=True, status=1).order_by('-create_time')

        def get_child_comments(parent_comment):
            child_qs = Comment.objects.filter(parent_comment_id=parent_comment.id, status=1).order_by('-create_time')
            child_comments = []
            for child in child_qs:
                comment_dict = {
                    **model_to_dict(child),
                    "first_name": child.user.first_name,
                    "user_id": child.user.id,
                    "ava": child.user.ava,
                    "create_time": child.create_time.strftime('%Y-%m-%d %H:%M:%S'),
                    "children": get_child_comments(child)
                }
                child_comments.append(comment_dict)
            return child_comments

        res_data = []
        for comment in top_qs:
            comment_dict = {
                **model_to_dict(comment),
                "first_name": comment.user.first_name,
                "user_id": comment.user.id,
                "ava": comment.user.ava,
                "create_time": comment.create_time.strftime('%Y-%m-%d %H:%M:%S'),
                "children": get_child_comments(comment)
            }
            res_data.append(comment_dict)
        return JsonResponse({"code": 0, "msg": "", "data": res_data})
    except Exception as e:
        print(e)
        return JsonResponse({"code": 9, "msg": str(e), "data": {}})


@is_login
def add_comment(request):
    if request.method == 'POST':
        try:
            rd = json.loads(request.body)
            # 获取当前用户id
            user_id = get_current_user(request)
            Comment.objects.create(
                content=rd.get('content'),
                parent_comment_id=rd.get('parent_comment_id'),
                article_id=rd.get('article_id'),
                user_id=user_id,
            )
            return JsonResponse({"code": 0, "msg": "提交成功", "data": {}})
        except Exception as e:
            print(e)
            return JsonResponse({"code": 9, "msg": str(e), "data": {}})


@is_login
def delete_comment(request):
    if request.method == 'POST':
        try:
            rd = json.loads(request.body)
            Comment.objects.filter(id=rd.get('id')).delete()
            return JsonResponse({"code": 0, "msg": "删除成功", "data": {}})
        except Exception as e:
            print(e)
            return JsonResponse({"code": 9, "msg": str(e), "data": {}})

def commentlist(request):
    if request.method == 'POST':
        rd = json.loads(request.body)
        qs = Comment.objects.filter(
            article__title__contains=rd.get('article_title',''),
            article__user__first_name__contains=rd.get('article_user_name',''),
            user__first_name__contains=rd.get('comment_user_name',''),
        ).order_by('-create_time')
        total = qs.count()
        qs = qs[(rd['page_index'] - 1) * rd['page_size']:(rd['page_index']) * rd['page_size']]
        res_data = [i.toDict() for i in qs]
        return JsonResponse({"code": 0, "msg": "", "data": {"data": res_data, "total": total}})
    elif request.method == 'GET':
        return render(request, 'commentlist.html')

def delete_comment_list(request):
    if request.method == 'POST':
        try:
            rd = json.loads(request.body)
            Comment.objects.filter(id__in=rd.get('ids')).delete()
            return JsonResponse({"code": 0, "msg": "删除成功", "data": {}})
        except Exception as e:
            print(e)
            return JsonResponse({"code": 9, "msg": str(e), "data": {}})

def update_comment_list(request):
    if request.method == 'POST':
        try:
            rd = json.loads(request.body)
            Comment.objects.filter(id=rd.get('id')).update(status=rd.get('status'))
            return JsonResponse({"code": 0, "msg": "修改成功", "data": {}})
        except Exception as e:
            print(e)
            return JsonResponse({"code": 9, "msg": str(e), "data": {}})

def get_article_list_by_type(request):
    if request.method == 'POST':
        rd = json.loads(request.body)
        # 获取所有分类
        types = Type.objects.all()
        data = [model_to_dict(type) for type in types]
        return JsonResponse({"code": 0, "msg": "", "data": data})
def get_rank_list(request):
    if request.method == 'POST':
        # 获取浏览量最高的10篇文章
        top_ten_articles = Article.objects.filter(examine=1,rang=1,status=1).order_by('-readers')[:10]
        articles_dict = [{**model_to_dict(article),"user_name":article.user.first_name,"count":article.readers} for article in top_ten_articles]
        # 获取收藏量最高的10篇文章
        top_ten_collected_articles_count = Collect.objects.values('article_id').annotate(count=Count('article_id')).order_by('-count')[:10]
        top_ten_collected_articles = Article.objects.filter(id__in=[article['article_id'] for article in top_ten_collected_articles_count])
        collected_articles_dict = [{**model_to_dict(article),"user_name":article.user.first_name,"count":Collect.objects.filter(article_id=article.id).count()} for article in top_ten_collected_articles]
        # 获取最新的10篇文章
        latest_ten_articles = Article.objects.filter(examine=1,rang=1,status=1).order_by('-create_time')[:10]
        latest_articles_dict = [{**model_to_dict(article),"user_name":article.user.first_name,"count":article.readers} for article in latest_ten_articles]
        return JsonResponse({"code": 0, "msg": "", "data": {
            "top_ten_articles": articles_dict,
            "top_ten_collected_articles": collected_articles_dict,
            "latest_ten_articles": latest_articles_dict
        }})

def reportArticle(request):
    if request.method == 'POST':
        rd = json.loads(request.body)
        # 获取当前用户id
        user_id = get_current_user(request)
        ReportArticle.objects.create(
            content=rd.get('content'),
            article_id=rd.get('article_id'),
            user_id=user_id,
        )
        return JsonResponse({"code": 0, "msg": "提交成功", "data": {}})
def reportComment(request):
    if request.method == 'POST':
        rd = json.loads(request.body)
        # 获取当前用户id
        user_id = get_current_user(request)
        ReportComment.objects.create(
            content=rd.get('content'),
            comment_id=rd.get('comment_id'),
            user_id=user_id,
        )
        return JsonResponse({"code": 0, "msg": "提交成功", "data": {}})
    
def reportlistArticle(request):
    if request.method == 'POST':
        rd = json.loads(request.body)
        qs = ReportArticle.objects.filter(
            content__contains=rd.get('content',''),
            user__first_name__contains=rd.get('reporter_name',''),
        ).order_by('-create_time')
        total = qs.count()
        qs = qs[(rd['page_index'] - 1) * rd['page_size']:(rd['page_index']) * rd['page_size']]
        res_data = [i.toDict() for i in qs]
        return JsonResponse({"code": 0, "msg": "", "data": {"data": res_data, "total": total}})
    elif request.method == 'GET':
        return render(request, 'reportlistArticle.html')
    
def delete_reportlistArticle(request):
    if request.method == 'POST':
        rd = json.loads(request.body)
        ReportArticle.objects.filter(id__in=rd.get('ids')).delete()
        return JsonResponse({"code": 0, "msg": "删除成功", "data": {}})


def reportlistComment(request):
    if request.method == 'POST':
        rd = json.loads(request.body)
        qs = ReportComment.objects.filter(
            content__contains=rd.get('content',''),
            user__first_name__contains=rd.get('reporter_name',''),
        ).order_by('-create_time')
        total = qs.count()
        qs = qs[(rd['page_index'] - 1) * rd['page_size']:(rd['page_index']) * rd['page_size']]
        res_data = [i.toDict() for i in qs]
        return JsonResponse({"code": 0, "msg": "", "data": {"data": res_data, "total": total}})
    elif request.method == 'GET':
        return render(request, 'reportlistComment.html')
    
def delete_reportlistComment(request):
    if request.method == 'POST':
        rd = json.loads(request.body)
        ReportComment.objects.filter(id__in=rd.get('ids')).delete()
        return JsonResponse({"code": 0, "msg": "删除成功", "data": {}})